#ifndef __IM_EVENT_ROLES_H__
#define __IM_EVENT_ROLES_H__

#include <im_base_types.h>
#include <im_object.h>

/**
 * @defgroup IMEventRoles
 * @ingroup PublicIME
 * @{
 */

/** @struct IMEventRoles
 *  @brief Class to hold one or more role informations of arbitrary event types.
 *
 * The role of an event means the role of an IMBUS component when dealing with the
 * event.
 *
 * For each event type, there are three different roles:
 * - Event producer
 *   Indicates that the component is able to produce that kind of event.
 * - Event consumer
 *   Indicates that the component is able to process that kind of event
 *   and return reply event if necessary.
 * - Event observer
 *   Indicates that the component is interested in that kind of event,
 *   but it won't return anything for the event.
 *
 * A component can act as multiple roles for one event type, for example,
 * An input method component can be producer as well as consumer of key events.
 *
 * An IMEventRoles object can hold role informations of arbitrary events for
 * an IMBUS component. The component can register its supported event roles
 * into IMBUS by sending an IMEventRoles object containing the information.
 *
 * IMBUS uses event roles information to distinguish each component.
 * But it's not necessary for a component to declare Event producer role of
 * an event type before sending such kind of events.
 * A component must declare Event consumer role of an event type if it wants
 * to process such kind of events, otherwise IMBUS won't deliver such kind of
 * eents to the component.
 *
 * There are mainly four different types of IMBUS components according to the
 * supported event roles:
 * - Input method component
 *   The component to provide input method service, which implements specified
 *   input method logic.
 * - Application component
 *   Each application is a component of IMBUS, which uses the service provided
 *   by Input method components.
 * - User interface component
 *   The component to provide user interface for IMBUS, which can be used by
 *   other components, especially input method components.
 * - Storage component
 *   The component to provide centrialized key-data based storage service,
 *   which can be used by other components to store configuration data.
 */

IM_BEGIN_DECLS
/** @brief cast the pointer to IMEventRoles*, return NULL if failed. */
#define IM_EVENT_ROLES(p)           (IM_TYPE_INSTANCE_CHECK_CAST((p),IM_TYPE_EVENT_ROLES,IMEventRoles))
/** @brief cast the pointer to const IMEventRoles*, return NULL if failed. */
#define IM_CONST_EVENT_ROLES(p)     (IM_TYPE_INSTANCE_CHECK_CAST_CONST((p),IM_TYPE_EVENT_ROLES,IMEventRoles))
/** @brief cast the pointer to IMEventRolesClass*, return NULL if failed. */
#define IM_EVENT_ROLES_CLASS(c)     (IM_TYPE_CLASS_CHECK_CAST((c),IM_TYPE_EVENT_ROLES,IMEventRolesClass))
/** @brief tell if the pointer is an instance of IMEventRoles. */
#define IM_IS_EVENT_ROLES(p)        (IM_TYPE_INSTANCE_CHECK_TYPE((p),IM_TYPE_EVENT_ROLES))
/** @brief tell if the pointer is IMEventRolesClass. */
#define IM_IS_EVENT_ROLES_CLASS(c)  (IM_TYPE_CLASS_CHECK_TYPE((c),IM_TYPE_EVENT_ROLES))
/** @brief get the type id from an instance of IMEventRoles. */
#define IM_EVENT_ROLES_GET_CLASS(p) (IM_TYPE_INSTANCE_GET_CLASS_CAST((p),IM_TYPE_EVENT_ROLES,IMEventRolesClass))

typedef struct _IMEventRoles         IMEventRoles;
typedef struct _IMEventRolesClass    IMEventRolesClass;
typedef struct _IMEventRolesIterator IMEventRolesIterator;

enum
{
    IM_EVENT_ROLE_PRODUCER = (1 << 0),
    IM_EVENT_ROLE_CONSUMER = (1 << 1),
    IM_EVENT_ROLE_OBSERVER = (1 << 2)
};

enum
{
    IM_EVENT_GROUP_COMMON_MANDATORY= 0,
    IM_EVENT_GROUP_IMBUS_MANDATORY,
    IM_EVENT_GROUP_IMBUS_OPTIONAL,
    IM_EVENT_GROUP_INPUT_METHOD_MANDATORY,
    IM_EVENT_GROUP_INPUT_METHOD_OPTIONAL,
    IM_EVENT_GROUP_UI_MANDATORY,
    IM_EVENT_GROUP_UI_OPTIONAL,
    IM_EVENT_GROUP_APPLICATION_MANDATORY,
    IM_EVENT_GROUP_APPLICATION_OPTIONAL,
    IM_EVENT_GROUP_STORAGE_MANDATORY,
    IM_EVENT_GROUP_STORAGE_OPTIONAL,
};

/**
 * @brief Create a new IMEventRoles object.
 *
 * Create a new IMEventRoles object, would could the this event role when you register
 * the component to handle the event into the imbus daemon. In case of the failure to
 * allocate new memory, it abort.
 *
 * @return void.
 */
IMEventRoles*       im_event_roles_new              ();

/**
 * @brief Clear a specified IMEventRoles object.
 *
 * This function removes all event roles information stored in a specified IMEventRoles
 * object.
 *
 * @param event_roles Event role to clear. If the event_roles is not valid, it aborts.
 * @return void.
 */
void                im_event_roles_clear            (IMEventRoles       *event_roles);

/**
 * @brief Set the roles of a specified event type in a IMEventRoles object.
 *
 * Old roles information for that event type will be replaced by the new one.
 *
 * @param event_roles Event role to set with event type and roles
 *              If event role is not the valid value, it would just return.
 * @param event_type Type id of the event.
 * @param roles Roles, bitmask of one or more of IM_EVENT_ROLE_PRODUCER,
 *              IM_EVENT_ROLE_CONSUMER or IM_EVENT_ROLE_OBSERVER.
 *              If roles is 0, it removes the role belong to the event.
 *
 * @return void.
 */
void                im_event_roles_set              (IMEventRoles       *event_roles,
                                                     IMUInt32            event_type,
                                                     IMUInt              roles);

/**
 * @brief Add a role to a specified event type in a IMEventRoles object.
 *
 * The new role will be added to the specified event type. Any available roles
 * for the event won't be touched.
 * @param event_role Event role to add
 *              If event_roles is not the valid value, it would just return.
 * @param event_type Type id of the event.
 * @param roles Roles, bitmask of one or more of IM_EVENT_ROLE_PRODUCER,
 *              IM_EVENT_ROLE_CONSUMER or IM_EVENT_ROLE_OBSERVER.
 * @return void.
 */
void                im_event_roles_add              (IMEventRoles       *event_roles,
                                                     IMUInt32            event_type,
                                                     IMUInt              roles);

/**
 * @brief Remove role information of a event type.
 *
 * All role information of specified event type will be removed.
 *
 * @param event_roles the role to modify
 *              If event_roles is not the valid value, it would just return.
 * @param event_type event type to remove, then the event_type became unkown to the event role
 * @return void.
 */
void                im_event_roles_remove           (IMEventRoles       *event_roles,
                                                     IMUInt32            event_type);

/**
 * @brief Get roles for a specified event type.
 *
 * Get the role information for the specified event type. The role information would be bitmask of producer, consumer and observer.
 *
 * @param event_roles The role to get the information from
 *              If event_roles is not the valid value, it would just return 0.
 * @param event_type Type id of the event.
 * @return The bitmasks of available roles, 0 if there is no role set to this event.
 */
IMUInt              im_event_roles_get              (const IMEventRoles *event_roles,
                                                     IMUInt32            event_type);

/**
 * @brief Check whether a role is set to a specified event type.
 *
 * Check if the role is associated with the specified event type.
 *
 * @param event_roles The role to check
 *              If event_roles is not the valid value, it would just return 0.
 * @param event_type Type id of the event.
 * @param role Type of the role to be checked.
 * @return TRUE if the role is set to the event else FALSE
 */
IMBool              im_event_roles_check            (const IMEventRoles *event_roles,
                                                     IMUInt32            event_type,
                                                     IMUInt              role);


IMEventRolesIterator* im_event_roles_get_iterator   (const IMEventRoles *event_roles);


IM_END_DECLS

#endif
/**  @} */

/*
vi:ts=4:nowrap:ai:expandtab
*/
